from random import normalvariate, uniform, gammavariate, randint

class Participante:
    def __init__(self, parametrosUsuario, perfil="racional"):
        self.valorParaParticipante = self.valorAleatorio(parametrosUsuario.distribuicaoValorParaParticipante, parametrosUsuario.parametrosValorParaParticipante)
        self.dinheiroDisponivel = self.valorAleatorio(parametrosUsuario.distribuicaoDinheiroDisponivel, parametrosUsuario.parametrosDinheiroDisponivel)

        #define a prioridade de cada participante fazer uma oferta
        self.tempoDeResposta = randint(1, 10)

        self.perfil = perfil

        if parametrosUsuario.perfeitamenteRacionais == True:
            self.funcaoParaCalcularOferta = self.ofertaPerfeitamenteRacional
        elif perfil == "cauteloso":
            self.funcaoParaCalcularOferta = self.ofertaParaPerfilCauteloso
        elif perfil == "moderado":
            self.funcaoParaCalcularOferta = self.ofertaParaPerfilModerado
        elif perfil == "agressivo":
            self.funcaoParaCalcularOferta = self.ofertaParaPerfilAgressivo

        self.participanteAliado = None
        self.participanteRival = None

    '''
    @return: retorna o valor da oferta,
    se quiser desistir do leilao retorna False,
    se nao quiser fazer uma oferta retorna None
    '''
    def fazOferta(self, ofertaInicial, ofertaAtual, aumentoMinimo, vencedorAtual):
        if vencedorAtual == self.participanteAliado:
            return None

        if aumentoMinimo <= 0:
            aumentoMinimo = 1

        rivalVencendo = False
        if vencedorAtual == self.participanteRival:
            rivalVencendo = True

        #depende se o participante eh perfeitamente racional ou nao
        return self.funcaoParaCalcularOferta(ofertaInicial, ofertaAtual, aumentoMinimo, rivalVencendo)

    def ofertaPerfeitamenteRacional(self, ofertaInicial, ofertaAtual, aumentoMinimo, rivalVencendo):
        if ofertaInicial > ofertaAtual:
            oferta = ofertaInicial
        else:
            oferta = ofertaAtual + aumentoMinimo

        if (oferta < self.valorParaParticipante and oferta < self.dinheiroDisponivel):
            return oferta
        else:
            return False

    def ofertaParaPerfilCauteloso(self, ofertaInicial, ofertaAtual, aumentoMinimo, rivalVencendo):
        if ofertaInicial > ofertaAtual:
            oferta = ofertaInicial
        elif ofertaAtual > .75 * self.valorParaParticipante:
            oferta = ofertaAtual + aumentoMinimo

        else:
            media = 1;
            if rivalVencendo == True:
                media += 0.5

            media *= aumentoMinimo

            aleatorio = self.valorAleatorio("normal", [media, aumentoMinimo / 4])

            if aleatorio < aumentoMinimo:
                oferta = aumentoMinimo + (aumentoMinimo - aleatorio)
            else:
                oferta = aleatorio

            oferta += ofertaAtual

        if oferta > self.dinheiroDisponivel or oferta > self.valorParaParticipante:
            return False
        else:
            return oferta

    def ofertaParaPerfilModerado(self, ofertaInicial, ofertaAtual, aumentoMinimo, rivalVencendo):
        if ofertaInicial > ofertaAtual:
            oferta = ofertaInicial
        else:
            media = 1.5
            if rivalVencendo == True:
                media += 0.5

            media *= aumentoMinimo

            aleatorio = -1
            while aleatorio < aumentoMinimo:
                aleatorio = self.valorAleatorio("normal", [media, .5 * aumentoMinimo])

            oferta = ofertaAtual + aleatorio

        if oferta > self.dinheiroDisponivel or oferta > self.valorParaParticipante:
            return False
        else:
            return oferta

    def ofertaParaPerfilAgressivo(self, ofertaInicial, ofertaAtual, aumentoMinimo, rivalVencendo):
        if ofertaInicial > ofertaAtual:
            oferta = ofertaInicial
        elif ofertaAtual > .75 * self.valorParaParticipante:
            oferta = self.valorParaParticipante
            if oferta > self.dinheiroDisponivel:
                oferta = self.dinheiroDisponivel

            if oferta < ofertaAtual + aumentoMinimo:
                return False
        else:
            media = 2
            if rivalVencendo == True:
                media += 0.5

            media *= aumentoMinimo

            aleatorio = -1
            while aleatorio < aumentoMinimo:
                aleatorio = self.valorAleatorio("normal", [media, .5 * aumentoMinimo])

            oferta = ofertaAtual + aleatorio

        if oferta > self.dinheiroDisponivel or oferta > self.valorParaParticipante:
            return False
        else:
            return oferta

    def valorAleatorio(self, distribuicao, parametros):
        if distribuicao == "normal":
            resultado = normalvariate(parametros[0], parametros[1])

        elif distribuicao == "uniforme":
            resultado = uniform(parametros[0], parametros[1])

        elif distribuicao == "gamma":
            resultado = gammavariate(parametros[0], parametros[1])

        elif distribuicao == "fixo":
            resultado = parametros[0]

        try:
            resultado = int(resultado)
        except:
            resultado = None

        return resultado
